package com.oss.service.oss;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oss.dto.oss.positionmanage.CountDto;
import com.oss.dto.oss.trademanage.*;
import com.oss.entity.oss.TradeManage;
import com.oss.enums.BuyOrSellEnum;
import com.oss.enums.IsDeletedEnum;
import com.oss.mapper.oss.TradeManageMapper;
import com.oss.service.system.DictionaryService;
import com.oss.service.system.UserService;
import com.oss.util.SnowFlakeUtil;
import com.oss.vo.oss.student.StudentVO;
import com.oss.vo.oss.trade.TradeManageVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chengqiang
 */
@Service
public class TradeManageService extends ServiceImpl<TradeManageMapper, TradeManage> {
    @Autowired
    DictionaryService dictionaryService;
    @Autowired
    StudentService studentService;
    @Autowired
    UserService userService;
    @Autowired
    HttpServletRequest request;
    @Autowired
    InstrumentService instrumentService;
    @Autowired
    LastPriceService lastPriceService;
    @Autowired
    CalendarService calendarService;

    public IPage<TradeManageVO> selectByPage(TradeManagePageDto dto) {
        LambdaQueryWrapper<TradeManage> wrapper = new LambdaQueryWrapper<TradeManage>();
        wrapper.eq(TradeManage::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.eq(StringUtils.isNotBlank(dto.getInstrumentCode()),TradeManage::getInstrumentCode, dto.getInstrumentCode());
        wrapper.eq(StringUtils.isNotBlank(dto.getStudentID()),TradeManage::getStudentID, dto.getStudentID());
        wrapper.eq(StringUtils.isNotBlank(dto.getOffsetFlag()),TradeManage::getOffsetFlag, dto.getOffsetFlag());
        wrapper.eq(dto.getSpeculationArbitrageFlag()!=null,TradeManage::getTaxFlag, dto.getSpeculationArbitrageFlag());
        if (dto.getTradeDateStart() != null){
            wrapper.ge(TradeManage::getTradeDate,dto.getTradeDateStart());
        }
        if (dto.getTradeDateEnd() != null){
            wrapper.le(TradeManage::getTradeDate,dto.getTradeDateEnd());
        }
        String originHeader = request.getHeader("oss-origin");
        String roleHeader = request.getHeader("oss-role");
        String studentID = request.getHeader("oss-studentID");
        // 校验用户角色 , 如果角色是admin,则查询所有数据
        if (StringUtils.isNotBlank(roleHeader) && roleHeader.contains("admin")) {

        } else {
            // 后台管理端和网页, 只要不是admin角色, 登录时, 只能查询自己账号新增的数据
            // dataSource=1表示系统新增
            wrapper.eq(TradeManage::getDataSource,1);
            wrapper.eq(TradeManage::getStudentID,studentID);
        }

        IPage<TradeManage> page = this.page(new Page<>(dto.getPageNo(), dto.getPageSize()), wrapper);
        Map<String,String> dictionaryMap = new HashMap<>();
        Map<String, StudentVO> studentMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(page.getRecords())){
            // 获取期权类型字典值
            dictionaryMap = dictionaryService.getDictionaryMapByTypeCode("OptionType");
            Set<String> ids = page.getRecords().stream().map(TradeManage::getStudentID).collect(Collectors.toSet());
            studentMap = studentService.selectByIDs(ids);
        }
        Map<String,String> userMap = new HashMap<>();
        Map<String,Integer> instrumentCodeMap = new HashMap<>();
        // 获取保证金比率 , key = 合约代码 , value = 比率
        Map<String,BigDecimal> tradeMarginRateMap = new HashMap<>();

        // key = 合约代码 ,value = 标的代码
        Map<String,String> underlyingCodeMap = new HashMap<>();
        // key = 标的代码 ,value = 最新价
        Map<String,BigDecimal> underlyingCodePriceMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            // 获取创建人和修改人ID
            Set<String> ids = page.getRecords().stream().map(TradeManage::getCreatorId).collect(Collectors.toSet());
            ids.addAll(page.getRecords().stream().map(TradeManage::getUpdatorId).collect(Collectors.toSet()));
            userMap = userService.selectByIds(ids);
            Set<String> instrumentCodeSet = page.getRecords().stream().map(TradeManage::getInstrumentCode).collect(Collectors.toSet());
            //tradeMarginRateMap = instrumentService.selectTradeMarginRateByInstrumentCodeSet(instrumentCodeSet);
            //instrumentCodeMap = instrumentService.selectByInstrumentCodeSet(instrumentCodeSet);
            //underlyingCodeMap = instrumentService.selectUnderlyingCodeByInstrumentCodeSet(instrumentCodeSet);
            //underlyingCodePriceMap = lastPriceService.selectByInstrumentCodeSetAndDate(underlyingCodeMap.values().stream().collect(Collectors.toSet()));
        }
        Map<String,String> buyOrSellMap = dictionaryService.getDictionaryMapByTypeCode("BuyOrSell");

        Map<String, String> finalDictionaryMap = dictionaryMap;
        Map<String, StudentVO> finalStudentMap = studentMap;
        Map<String, String> finalUserMap = userMap;
        Map<String, Integer> finalInstrumentCodeMap = instrumentCodeMap;
        Map<String, BigDecimal> finalUnderlyingCodePriceMap = underlyingCodePriceMap;
        Map<String, BigDecimal> finalTradeMarginRateMap = tradeMarginRateMap;
        Map<String, String> finalUnderlyingCodeMap = underlyingCodeMap;
        return page.convert(entity->{
            TradeManageVO vo = new TradeManageVO();
            BeanUtils.copyProperties(entity,vo);
            vo.setOptionType(finalDictionaryMap.get(entity.getOptionType()));
            if (finalStudentMap.containsKey(entity.getStudentID())){
                StudentVO studentVO = finalStudentMap.get(entity.getStudentID());
                vo.setStudentID(studentVO.getId());
                vo.setStudentPhone(studentVO.getPhone());
                vo.setStudentName(studentVO.getName());
                vo.setStudentWechatID(studentVO.getWechatID());
                vo.setStudentAccount(studentVO.getAccount());
            }
            vo.setCreatorName(finalUserMap.get(entity.getCreatorId()));
            vo.setUpdatorName(finalUserMap.get(entity.getUpdatorId()));
            vo.setOffsetFlag(buyOrSellMap.get(entity.getOffsetFlag()));
            String instrumentCode = entity.getInstrumentCode();
            // 交易单位
            Integer volumeMultiple = finalInstrumentCodeMap.get(entity.getInstrumentCode());
            BigDecimal volumeMultipleTemp = volumeMultiple==null?BigDecimal.ZERO:new BigDecimal(volumeMultiple);
            BigDecimal tradeVolume = entity.getTradeVolume() == null ? BigDecimal.ZERO : entity.getTradeVolume();
            BigDecimal tradeSinglePrice = entity.getTradeSinglePrice() == null ? BigDecimal.ZERO : entity.getTradeSinglePrice();
//            BigDecimal volumeMultipleTemp = volumeMultiple==null?BigDecimal.ZERO:new BigDecimal(volumeMultiple);
//            BigDecimal tradeSinglePrice = entity.getTradeSinglePrice() == null ? BigDecimal.ZERO : entity.getTradeSinglePrice();
//            BigDecimal premium = tradeVolume.multiply(tradeSinglePrice).multiply(volumeMultipleTemp);
            // 卖开的权利金为负数
//            if (entity.getOffsetFlag().equals(BuyOrSellEnum.SellCall.getValue())) {
//                premium = premium.multiply(new BigDecimal(-1));
//            }
            //vo.setPremium(premium);
            //BigDecimal lastPrice = finalUnderlyingCodePriceMap.get(finalUnderlyingCodeMap.get(entity.getInstrumentCode()));
            //lastPrice = lastPrice == null ? BigDecimal.ZERO : lastPrice;
            //BigDecimal tradeMarginRate = finalTradeMarginRateMap.get(entity.getInstrumentCode());
            //tradeMarginRate = tradeMarginRate == null ? BigDecimal.ZERO : tradeMarginRate;
            //vo.setTradeMargin(lastPrice.multiply(volumeMultipleTemp).multiply(tradeMarginRate));
            // 交易保证金计算的合约单价
            BigDecimal tradeMarginLastPrice = instrumentService.getTradeMarginLastPriceByInstrumentCode(instrumentCode);
            BigDecimal tradeMarginRate = instrumentService.getRateByInstrumentCode(instrumentCode);
            BigDecimal premium = tradeVolume.multiply(tradeSinglePrice).multiply(volumeMultipleTemp);
            if (entity.getOffsetFlag().equals(BuyOrSellEnum.SellCall.getValue())) {
                // 卖开的权利金为负数
                premium = premium.negate();
                BigDecimal tradeMargin = tradeMarginLastPrice.multiply(volumeMultipleTemp).multiply(tradeMarginRate);
                vo.setTradeMargin(tradeMargin);
            }
            vo.setPremium(premium);
            vo.setPremium(entity.getPremium());
            return vo;
        });
    }

    public String add(TradeManageAddDto dto) {
        TradeManage entity = new TradeManage();
        BeanUtils.copyProperties(dto,entity);
        entity.setId(SnowFlakeUtil.getID());
        entity.setDataSource(1);
//        BigDecimal volumeMultiple = instrumentService.getVolumeMultipleByInstrumentCode(dto.getInstrumentCode());
//        BigDecimal tradeMarginRate = instrumentService.getRateByInstrumentCode(dto.getInstrumentCode());
//        BigDecimal premium = entity.getTradeSinglePrice().multiply(dto.getTradeVolume()).multiply(volumeMultiple);
//        // 买开/平的权利金为负数
//        if (entity.getOffsetFlag().equals(BuyOrSellEnum.BuyCall.getValue()) || entity.getOffsetFlag().equals(BuyOrSellEnum.BuyPut.getValue())) {
//            premium = premium.multiply(new BigDecimal(-1));
//        }
//        entity.setPremium(premium);
//        // 交易归属为夜盘 , 交易日期往后找最近的一个交易日
//        if (dto.getBelongFlag() != null && 1 == dto.getBelongFlag()){
//            LocalDate date = calendarService.getNextTradingDay(dto.getTradeDate());
//            entity.setTradeDate(date);
//        }
//        if (entity.getOffsetFlag().equals(BuyOrSellEnum.SellCall.getValue())){
//            BigDecimal tradeMargin = instrumentService.getTradeMarginLastPriceByInstrumentCode(dto.getInstrumentCode())
//                    .multiply(volumeMultiple).multiply(tradeMarginRate).multiply(dto.getTradeVolume());
//            entity.setTradeMargin(tradeMargin);
//        } else {
//            entity.setTradeMargin(BigDecimal.ZERO);
//        }
        boolean flag = calendarService.isTradeingDay(dto.getTradeDate());
        if (flag == false) {
            LocalDate date = calendarService.getNextTradingDay(dto.getTradeDate());
            entity.setTradeDate(date);
        }
        this.save(entity);
        return "操作成功";
    }


    public String updateData(TradeManageUpdateDto dto) {
        TradeManage entity = new TradeManage();
        BeanUtils.copyProperties(dto,entity);
//        BigDecimal volumeMultiple = instrumentService.getVolumeMultipleByInstrumentCode(dto.getInstrumentCode());
//        BigDecimal tradeMarginRate = instrumentService.getRateByInstrumentCode(dto.getInstrumentCode());
//        BigDecimal premium = entity.getTradeSinglePrice().multiply(dto.getTradeVolume()).multiply(volumeMultiple);
//        // 买开/平的权利金为负数
//        if (entity.getOffsetFlag().equals(BuyOrSellEnum.BuyCall.getValue()) || entity.getOffsetFlag().equals(BuyOrSellEnum.BuyPut.getValue())) {
//            premium = premium.multiply(new BigDecimal(-1));
//        }
//        if (entity.getOffsetFlag().equals(BuyOrSellEnum.SellCall.getValue())){
//            BigDecimal tradeMargin = instrumentService.getTradeMarginLastPriceByInstrumentCode(dto.getInstrumentCode())
//                    .multiply(volumeMultiple).multiply(tradeMarginRate).multiply(dto.getTradeVolume());
//            entity.setTradeMargin(tradeMargin);
//        } else {
//            entity.setTradeMargin(BigDecimal.ZERO);
//        }
//        entity.setPremium(premium);
        // 交易归属为夜盘 , 交易日期往后找最近的一个交易日
        boolean flag = calendarService.isTradeingDay(dto.getTradeDate());
        if (flag == false) {
            LocalDate date = calendarService.getNextTradingDay(dto.getTradeDate());
            entity.setTradeDate(date);
        }
        this.updateById(entity);
        return "操作成功";
    }

    public String delete(TradeManageDeleteDto dto) {
        LambdaUpdateWrapper<TradeManage> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(TradeManage::getId,dto.getId());
        lambdaUpdateWrapper.set(TradeManage::getIsDeleted,IsDeletedEnum.YES.getFlag());
        this.update(null,lambdaUpdateWrapper);
        return "操作成功";
    }

    /**
     * 先删除(根据交易日期, 合约代码 , 数据来源)
     * @param tradeDate
     * @param instrumentCode
     */
    public void deleteByTradeCodeAndTradeDate(String studentID,LocalDate tradeDate,String instrumentCode){
        LambdaUpdateWrapper<TradeManage> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(TradeManage::getInstrumentCode,instrumentCode);
        wrapper.eq(TradeManage::getStudentID,studentID);
        wrapper.eq(TradeManage::getTradeDate,tradeDate);
        wrapper.eq(TradeManage::getDataSource,0);
        wrapper.set(TradeManage::getIsDeleted,IsDeletedEnum.YES.getFlag());
        this.update(null,wrapper);
    }

    public String importData(TradeManageImportDto dto) {
        List<TradeManage> addList = new ArrayList<>();
        Set<String> accountSet = dto.getList().stream().map(TradeManageImportDetailDto::getAccount).collect(Collectors.toSet());
        Map<String, String> studentAccountMap = studentService.getByAccountSet(accountSet);
        for (TradeManageImportDetailDto item : dto.getList()) {
            deleteByTradeCodeAndTradeDate(studentAccountMap.get(item.getAccount()),item.getTradeDate(),item.getInstrumentCode());
            TradeManage entity = new TradeManage();
            BeanUtils.copyProperties(item,entity);
            entity.setId(SnowFlakeUtil.getID());
            entity.setDataSource(0);
            entity.setStudentID(studentAccountMap.get(item.getAccount()));
            entity.setCreatorId("-1");
            addList.add(entity);
        }
        if (CollectionUtils.isNotEmpty(addList)){
            this.saveBatch(addList);
        }
        return "操作成功";
    }

    public List<TradeManage> getByInstrumentCode(String instrumentCode) {
        LambdaQueryWrapper<TradeManage> wrapper = new LambdaQueryWrapper<TradeManage>();
        wrapper.eq(TradeManage::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.eq(TradeManage::getInstrumentCode, instrumentCode);
        return  this.list(wrapper);
    }

    /**
     * 查询今日交易数据
     * @return
     */
    public List<TradeManage> selectCurrnetDayDataBySIdAndVarietyCode(CountDto dto) {
        LambdaQueryWrapper<TradeManage> wrapper = new LambdaQueryWrapper<TradeManage>();
        wrapper.eq(TradeManage::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.eq(TradeManage::getTradeDate, dto.getPositionDate());
        wrapper.in(TradeManage::getStudentID, dto.getStudentIDs());
        return  this.list(wrapper);
    }
}
